fn main() {
    let u1 = build_user(
        String::from("skyjiang"), 
        String::from("skyjiang@qq.com")
    );

    // u1中部分字段是所有权发生转移，u1不可用
    // 用一个结构体更新另一个结构体, 必须在结构体结尾
    let mut u2 = User {
        username: String::from("xiao_ming"),
        ..u1
    };

    // u1中未转移所有权的字段依然可用
    //println!("{:?}", u1) // 报错
    println!("username: {}, active: {}", u1.username, u1.active);

    u2.change_name(String::from("xiao_fang"));
    println!("u2 name: {}", u2.username);

    let u3 = User::create_user(String::from("jack"));
    //println!("{}", u3);        // 以{}打印结构体需要实现Display特征
    println!("{:?} \n{:#?}", u3, u3);  // 需要实现Debug特征
    let _s3 = dbg!(u3); // dbg宏打印信息, 会获取所有权并返回

    // --------------
    let tup = (1, 1.2, "str");
    let (x, y, z) = tup;  // 用模式匹配结构元组
    println!("idx 1: {}, {}", tup.0, x);  // 元组索引从0开始

    // --------------
    let blank = Color(0, 0, 0);
    println!("color: {}", blank.1);
}

#[derive(Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

// 函数
fn build_user(username: String, email: String) -> User {
    // 定义结构体时, 每个字段都需要初始化, 
    // 但初始化顺序不需要与定义顺序一致
    User{
        username, // 与参数同名
        email,
        sign_in_count: 1,
        active: true,
    }
}

impl User {
    fn total_count(&self) -> u64 {
        self.sign_in_count   
    }

    fn change_name(&mut self, new_name: String) {
        self.username = new_name
    }

    // 关联函数 定义在impl块内，但不与具体对象相关联
    // 用 结构体名::xxx 调用
    fn create_user(username: String) -> User {
        User {  
            username,
            email: String::new(),
            sign_in_count: 1,
            active: true,
        }
    }
}


// 结构体必须要有名称，但是结构体的字段可以没有名称
// 这种结构体像元组, 因此称为 元组结构体 
struct Color(i32, i32, i32);

// 单元结构体
// 不关心结构体中的内容, 只关心其行为 (可为其实现特征)
struct AlwaysEqual;

